This is an R Markdown Notebook. When you execute code within the notebook, the results appear beneath the code.

Reverse Engineer 2 Notebook

Objective: Analyze data from the Blair and Elrich campaigns for county executive from 2018 and 2022.

###Question 1:

First thing we did is load up the sets and clean the data:

##Blair 2018 contribs:

blair_contribs_2018 <-read.csv("data2/blair_contribs_2018.csv")
blair_contribs_2018_cleaned <-blair_contribs_2018 %>% 
clean_names  
  
  
blair_contribs_2018_cleaned %>%   
mutate(contribution_date = mdy(contribution_date)) 
blair_contribs_2018_cleaned

###Blair 2022 contribs

blair_contribs_2022 <-read.csv("data2/blair_contribs_2022.csv")
blair_contribs_2022_cleaned <- blair_contribs_2022 %>% 
clean_names 
blair_contribs_2022_cleaned %>% 
mutate(contribution_date = mdy(contribution_date)) 

blair_contribs_2022_cleaned

###Blair 2022 expenses

blair_expenses_2022 <-read.csv("data2/blair_expenses_2022.csv")
blair_expenses_2022_cleaned <-blair_expenses_2022 %>% 
  clean_names 
blair_expenses_2022_cleaned %>% 
mutate(contribution_date = mdy(expenditure_date)) 

blair_expenses_2022_cleaned

###Blair 2018 expenses

blair_expenses_2018 <-read.csv("data2/blair_expenses_2018.csv")
blair_expenses_2018_cleaned <-blair_expenses_2018 %>% 
  clean_names()
blair_expenses_2018_cleaned %>% 
  mutate(contribution_date = mdy(expenditure_date)) 
blair_expenses_2018_cleaned 

##Elrich 2018 contribs:

elrich_contribs_2018 <-read.csv("data2/elrich_contribs_2018.csv")
elrich_contribs_2018_cleaned <-elrich_contribs_2018 %>% 
  clean_names()
elrich_contribs_2018_cleaned %>% 
  mutate(contribution_date = mdy(contribution_date)) 

elrich_contribs_2018_cleaned

###Elrich Contribs 2022

elrich_contribs_2022 <-read.csv("data2/elrich_contribs_2022.csv")
elrich_contribs_2022_cleaned <-elrich_contribs_2022 %>%
  clean_names()
elrich_contribs_2022_cleaned %>% 
  mutate(contribution_date = mdy(contribution_date)) 

elrich_contribs_2022_cleaned

###Elrich 2018

elrich_expenses_2018 <-read.csv("data2/elrich_expenses_2018.csv")
elrich_expenses_2018_cleaned <-elrich_expenses_2018 %>% 
  clean_names()
elrich_expenses_2018_cleaned %>% 
    mutate(contribution_date = mdy(expenditure_date)) 
elrich_expenses_2018_cleaned

###Elrich Expenses 2022

elrich_expenses_2022 <-read.csv("data2/elrich_expenses_2022.csv")
elrich_expenses_2022_cleaned <-elrich_expenses_2022 %>% 
  clean_names()
elrich_expenses_2022_cleaned %>% 
  mutate(contribution_date = mdy(expenditure_date)) 
elrich_expenses_2022_cleaned

##County primary election results:

dem_precincts_18 <- read.csv("data2/dem_precincts_2018.csv")
dem_precincts_22 <- read.csv("data2/dem_precincts_2022.csv")
dem_county_22 <- read.csv("data2/dem_county_2022.csv")
dem_county_18 <- read.csv("data2/dem_county_2018.csv")

###Question 1 1. How much money did David Blair and Marc Elrich fund themselves in 2022 vs. 2018? Blair is a businessman and millionaire, so it makes sense that he’s funding his own campaign. But how much exactly is he putting into it, and how does it compare to the past election and to how much Elrich’s campaign is raising?

###2022:

blair_contribs_2022_cleaned %>%
filter(contributor_name == "BLAIR  DAVID  THOMAS") %>%
group_by(contributor_name) %>%
summarize(total_blair = sum(contribution_amount))
elrich_contribs_2022_cleaned %>%
group_by(contributor_name) %>%
summarize(total_elrich = sum(contribution_amount)) %>%
arrange(desc(total_elrich))

###2018:

blair_contribs_2018_cleaned %>%
filter(contributor_name == "BLAIR  DAVID  THOMAS") %>%
group_by(contributor_name) %>%
summarize(total_blair = sum(contribution_amount))
elrich_contribs_2018_cleaned %>%
group_by(contributor_name) %>%
summarize(total_elrich = sum(contribution_amount)) %>%
arrange(desc(total_elrich))

###Question 2: Who were the top 5 contributors to Blair and Elrich in 2022? How about in 2018? What are their connections to the candidates?

###2022

top_blair_contribs_22 <- blair_contribs_2018_cleaned %>%
  mutate(contributor_name = case_when(
    contributor_name == "BLAIR  DAVID  THOMAS" ~ "Blair  David  Thomas",
    TRUE ~ contributor_name
  )) %>%
  group_by(contributor_name) %>%
  summarize(total = sum(contribution_amount)) %>%
  arrange(desc(total)) %>%
  head(5)
top_blair_contribs_22
top_elrich_contribs_22 <- elrich_contribs_2022_cleaned %>%
  group_by(contributor_name) %>%
  summarize(total = sum(contribution_amount)) %>%
  arrange(desc(total)) %>%
  head(6)
top_elrich_contribs_22

###2018

top_blair_contribs_18 <- blair_contribs_2018_cleaned %>%
  mutate(contributor_name = case_when(
    contributor_name == "BLAIR  DAVID  THOMAS" ~ "Blair  David  Thomas",
    TRUE ~ contributor_name
  )) %>%
  group_by(contributor_name) %>%
  summarize(total = sum(contribution_amount)) %>%
  arrange(desc(total)) %>%
  head(5)
top_blair_contribs_18
top_elrich_contribs_18 <- elrich_contribs_2018_cleaned %>%
  group_by(contributor_name) %>%
  summarize(total = sum(contribution_amount)) %>%
  arrange(desc(total)) %>%
  head(6)
top_elrich_contribs_18

###Question 3: David Blair got more early/election day votes in 2022. Elrich got more Mail-in votes in 2022. How did that compare to 2018? People want to know how Marc Elrich won both times, first by 72 voters in 2018 and then 32 in 2022. Where did Marc do well in the three categories: Early voting, election day, and mail-in votes. Did this sway the result at all?

dem_county_18_cleaned <-dem_county_18 %>% 
  clean_names()
dem_county_22_cleaned <-dem_county_22 %>% 
  clean_names()

blair <- dem_county_18_cleaned %>%
filter(candidate_name == "David Blair")
elrich <-  dem_county_18_cleaned %>%
  filter(candidate_name == "Marc Elrich")
blair_elrich <-  bind_rows(blair, elrich)
blair_elrich

###Question 4: Which parts of the county voted for Elrich and which voted for Blair based on precinct-level voting? Are there differences in demographics of those areas? What about income?

\

library(sf)
Linking to GEOS 3.9.1, GDAL 3.4.3, PROJ 7.2.1; sf_use_s2() is TRUE
moco_prec_2022 <- st_read("data2/MontMD_2022/MontMD_2022.shp") %>% 
  st_zm(drop=TRUE)
Reading layer `MontMD_2022' from data source 
  `C:\Users\merca\Documents\GitHub\data_journalism_fall_2022\major_assignments\reverse_engineering\data2\MontMD_2022\MontMD_2022.shp' 
  using driver `ESRI Shapefile'
Simple feature collection with 261 features and 5 fields
Geometry type: MULTIPOLYGON
Dimension:     XYZM
Bounding box:  xmin: 1162792 ymin: 461729.6 xmax: 1344207 ymax: 614681.3
z_range:       zmin: 0 zmax: 0
m_range:       mmin: 0 mmax: 0
Projected CRS: NAD83 / Maryland (ftUS)
glimpse(moco_prec_2022)
Rows: 261
Columns: 6
$ NAME     <chr> "MONTGOMERY PRECINCT 07-032", "MONTGOMERY PRECINCT 09-015", "MONTGOMERY PRECINCT 13-056", "M…
$ NUMBER   <chr> "07-032", "09-015", "13-056", "13-016", "01-006", "04-027", "08-008", "08-016", "10-001", "0…
$ JURSCODE <chr> "MONT", "MONT", "MONT", "MONT", "MONT", "MONT", "MONT", "MONT", "MONT", "MONT", "MONT", "MON…
$ VOTESPRE <chr> "007-032", "009-015", "013-056", "013-016", "001-006", "004-027", "008-008", "008-016", "010…
$ COUNCIL  <chr> "1", "3", "6", "4", "7", "6", "7", "7", "1", "6", "7", "1", "1", "7", "4", "3", "3", "2", "6…
$ geometry <MULTIPOLYGON [US_survey_foot]> MULTIPOLYGON (((1289150 485..., MULTIPOLYGON (((1251625 546..., MU…
moco_boundaries <- st_read("data2/moco_boundary.gdb")
Reading layer `CNTY_BNDY' from data source 
  `C:\Users\merca\Documents\GitHub\data_journalism_fall_2022\major_assignments\reverse_engineering\data2\moco_boundary.gdb' 
  using driver `OpenFileGDB'
Simple feature collection with 1 feature and 3 fields
Geometry type: MULTIPOLYGON
Dimension:     XY
Bounding box:  xmin: -77.52769 ymin: 38.93425 xmax: -76.88764 ymax: 39.35434
Geodetic CRS:  WGS 84
glimpse(moco_boundaries)
Rows: 1
Columns: 4
$ NAME         <chr> "MONTGOMERY COUNTY"
$ SHAPE_Length <dbl> 1.895903
$ SHAPE_Area   <dbl> 0.1367927
$ SHAPE        <MULTIPOLYGON [°]> MULTIPOLYGON (((-77.18523 3...
moco_boundaries %>%
  ggplot() +
  geom_sf() +
  theme_minimal()

moco_prec_2022
Simple feature collection with 261 features and 5 fields
Geometry type: MULTIPOLYGON
Dimension:     XY
Bounding box:  xmin: 1162792 ymin: 461729.6 xmax: 1344207 ymax: 614681.3
Projected CRS: NAD83 / Maryland (ftUS)
First 10 features:
                         NAME NUMBER JURSCODE VOTESPRE COUNCIL                       geometry
1  MONTGOMERY PRECINCT 07-032 07-032     MONT  007-032       1 MULTIPOLYGON (((1289150 485...
2  MONTGOMERY PRECINCT 09-015 09-015     MONT  009-015       3 MULTIPOLYGON (((1251625 546...
3  MONTGOMERY PRECINCT 13-056 13-056     MONT  013-056       6 MULTIPOLYGON (((1301382 519...
4  MONTGOMERY PRECINCT 13-016 13-016     MONT  013-016       4 MULTIPOLYGON (((1298182 487...
5  MONTGOMERY PRECINCT 01-006 01-006     MONT  001-006       7 MULTIPOLYGON (((1268938 556...
6  MONTGOMERY PRECINCT 04-027 04-027     MONT  004-027       6 MULTIPOLYGON (((1280700 512...
7  MONTGOMERY PRECINCT 08-008 08-008     MONT  008-008       7 MULTIPOLYGON (((1282944 540...
8  MONTGOMERY PRECINCT 08-016 08-016     MONT  008-016       7 MULTIPOLYGON (((1295564 548...
9  MONTGOMERY PRECINCT 10-001 10-001     MONT  010-001       1 MULTIPOLYGON (((1247972 509...
10 MONTGOMERY PRECINCT 04-026 04-026     MONT  004-026       6 MULTIPOLYGON (((1285712 505...
head(moco_prec_2022)
Simple feature collection with 6 features and 5 fields
Geometry type: MULTIPOLYGON
Dimension:     XY
Bounding box:  xmin: 1246398 ymin: 481181.4 xmax: 1302601 ymax: 556657.3
Projected CRS: NAD83 / Maryland (ftUS)
                        NAME NUMBER JURSCODE VOTESPRE COUNCIL                       geometry
1 MONTGOMERY PRECINCT 07-032 07-032     MONT  007-032       1 MULTIPOLYGON (((1289150 485...
2 MONTGOMERY PRECINCT 09-015 09-015     MONT  009-015       3 MULTIPOLYGON (((1251625 546...
3 MONTGOMERY PRECINCT 13-056 13-056     MONT  013-056       6 MULTIPOLYGON (((1301382 519...
4 MONTGOMERY PRECINCT 13-016 13-016     MONT  013-016       4 MULTIPOLYGON (((1298182 487...
5 MONTGOMERY PRECINCT 01-006 01-006     MONT  001-006       7 MULTIPOLYGON (((1268938 556...
6 MONTGOMERY PRECINCT 04-027 04-027     MONT  004-027       6 MULTIPOLYGON (((1280700 512...
write_csv(moco_prec_2022, "data2/moco_prec_2022.csv")
moco_prec_2022 %>%
  ggplot() +
  geom_sf() +
  theme_minimal()

moco_22_pre_results<-read.csv("data2/Moco_22_pre_results.csv")
head(moco_22_pre_results)
moco_22_pre_results_cleaned <-moco_22_pre_results %>% 
  clean_names()
moco_22_pre_results_cleaned
moco_22_pre_results_filtered<-moco_22_pre_results_cleaned %>%
filter(candidate_name == "David T. Blair" | candidate_name == "Marc Elrich")
moco_22_pre_results_filtered
blair_results_2022_filter<-moco_22_pre_results_filtered %>% 
  filter(candidate_name == "David T. Blair")
blair_results_2022_filter
blair_results_2022_filter_total <-blair_results_2022_filter%>% 
  mutate(total_votes_blair = early_votes + election_night_votes + mail_in_ballot_1_votes + provisional_votes + mail_in_ballot_2_votes)
blair_results_2022_filter_total
blair_results_joined_2022<- inner_join(moco_prec_2022, blair_results_2022_filter_total, by=c("VOTESPRE"="election_district_precinct"))

###Blair Map####

ggplot() +
  geom_sf(data=blair_results_joined_2022, aes(fill=total_votes_blair)) +
  scale_fill_viridis_b(option="magma")+
  theme_minimal()

####Elirich map####

moco_22_pre_results_filtered_elrich <-moco_22_pre_results_cleaned %>%
filter(candidate_name == "Marc Elrich")
moco_22_pre_results_filtered_elrich
elrich_22_filtered_total <-moco_22_pre_results_filtered_elrich%>% 
  mutate(total_votes_elrich = early_votes + election_night_votes + mail_in_ballot_1_votes + provisional_votes + mail_in_ballot_2_votes)
elrich_22_filtered_total
elrich_results_joined_2022_map<- inner_join(moco_prec_2022, elrich_22_filtered_total, by=c("VOTESPRE"="election_district_precinct"))
ggplot() +
  geom_sf(data=elrich_results_joined_2022_map, aes(fill=total_votes_elrich)) +
  scale_fill_viridis_b(option="magma")+
  theme_minimal()

###percentage_change***

blair_results_2022_filter_total
elrich_22_filtered_total
both_joined_2022<- left_join(blair_results_2022_filter_total, elrich_22_filtered_total, by=c("county"="county"))
both_joined_2022
both_joined_mutated<-both_joined_2022 %>% 
  mutate(difference = total_votes_elrich-total_votes_blair)
both_joined_mutated
NA
both_joined_map<- inner_join(moco_prec_2022, both_joined_mutated, by=c("VOTESPRE"="election_district_precinct.x"))
ggplot() +
  geom_sf(data=both_joined_map, aes(fill=difference)) +
  scale_fill_viridis_b(option="magma")+
  theme_minimal()

library(ggplot2)
ggplot(results_joined_2022)+
  geom_map(aes(map_id = region))+
  expand_limits()

###Question 5: Where did David Blair and Marc Elrich spend their money on campaign finance resources? Ie: Meta advertisements, yard signs, TV, consulting? This would be interesting to know since Blair made a very big concerted effort to build his profile during the campaign while Elrich relied on incumbency and mainly TV ads to help him.

blair_expenses_2022_cleaned %>%
group_by(expense_category) %>%
summarize(total_category = sum(amount)) %>%
arrange(desc(total_category))
#spent nearly $3.1 mil in 2022 ... top 3 are Media, Salarties and Direct Mail by Mail House (R)

#dive into media

blair_expenses_2022_cleaned %>%
filter(expense_category == "Media") %>%
group_by(expense_purpose) %>%
summarize(total_category = sum(amount)) %>%
arrange(desc(total_category))

Spent 1773.00 on online advertising

elrich_expenses_2022_cleaned %>%
group_by(expense_category) %>%
summarize(total_category = sum(amount)) %>%
arrange(desc(total_category))

Elrich spent $528393.29 on media which is significantly less than Blair

elrich_expenses_2022_cleaned %>%
filter(expense_category == "Media") %>%
group_by(expense_purpose) %>%
summarize(total_category = sum(amount)) %>%
arrange(desc(total_category))

#Elrich spent 32K on consulting fees.

This is what I wrote for No. 5 “There are signifant differences in spending between Elrich and Blair here and it shows how the capital on hand can really influence the means a candidate has to win or lose a race. Elrich in 2022 went all-in on TV spending. Blair spent a lot more in 2018 as well.”

LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpUaGlzIGlzIGFuIFtSIE1hcmtkb3duXShodHRwOi8vcm1hcmtkb3duLnJzdHVkaW8uY29tKSBOb3RlYm9vay4gV2hlbiB5b3UgZXhlY3V0ZSBjb2RlIHdpdGhpbiB0aGUgbm90ZWJvb2ssIHRoZSByZXN1bHRzIGFwcGVhciBiZW5lYXRoIHRoZSBjb2RlLiANCg0KDQpSZXZlcnNlIEVuZ2luZWVyIDIgTm90ZWJvb2sNCg0KT2JqZWN0aXZlOiBBbmFseXplIGRhdGEgZnJvbSB0aGUgQmxhaXIgYW5kIEVscmljaCBjYW1wYWlnbnMgZm9yIGNvdW50eSBleGVjdXRpdmUgZnJvbSAyMDE4IGFuZCAyMDIyLg0KDQojIyNRdWVzdGlvbiAxOg0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkNCmBgYA0KDQoNCmBgYHtyIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0V9DQpvcHRpb25zKHNjaXBlbj05OTkpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkobHVicmlkYXRlKQ0KbGlicmFyeShqYW5pdG9yKQ0KDQpgYGANCg0KDQoNCkZpcnN0IHRoaW5nIHdlIGRpZCBpcyBsb2FkIHVwIHRoZSBzZXRzIGFuZCBjbGVhbiB0aGUgZGF0YToNCg0KIyNCbGFpciAyMDE4IGNvbnRyaWJzOg0KDQpgYGB7cn0NCmJsYWlyX2NvbnRyaWJzXzIwMTggPC1yZWFkLmNzdigiZGF0YTIvYmxhaXJfY29udHJpYnNfMjAxOC5jc3YiKQ0KYGBgDQoNCmBgYHtyfQ0KYmxhaXJfY29udHJpYnNfMjAxOF9jbGVhbmVkIDwtYmxhaXJfY29udHJpYnNfMjAxOCAlPiUgDQpjbGVhbl9uYW1lcyAgDQogIA0KICANCmJsYWlyX2NvbnRyaWJzXzIwMThfY2xlYW5lZCAlPiUgICANCm11dGF0ZShjb250cmlidXRpb25fZGF0ZSA9IG1keShjb250cmlidXRpb25fZGF0ZSkpIA0KYmxhaXJfY29udHJpYnNfMjAxOF9jbGVhbmVkDQpgYGANCg0KDQojIyNCbGFpciAyMDIyIGNvbnRyaWJzDQoNCmBgYHtyfQ0KYmxhaXJfY29udHJpYnNfMjAyMiA8LXJlYWQuY3N2KCJkYXRhMi9ibGFpcl9jb250cmlic18yMDIyLmNzdiIpDQpgYGANCg0KYGBge3J9DQpibGFpcl9jb250cmlic18yMDIyX2NsZWFuZWQgPC0gYmxhaXJfY29udHJpYnNfMjAyMiAlPiUgDQpjbGVhbl9uYW1lcyANCmBgYCAgDQogIA0KYGBge3J9ICANCmJsYWlyX2NvbnRyaWJzXzIwMjJfY2xlYW5lZCAlPiUgDQptdXRhdGUoY29udHJpYnV0aW9uX2RhdGUgPSBtZHkoY29udHJpYnV0aW9uX2RhdGUpKSANCg0KYmxhaXJfY29udHJpYnNfMjAyMl9jbGVhbmVkDQpgYGANCg0KIyMjQmxhaXIgMjAyMiBleHBlbnNlcw0KDQpgYGB7cn0NCmJsYWlyX2V4cGVuc2VzXzIwMjIgPC1yZWFkLmNzdigiZGF0YTIvYmxhaXJfZXhwZW5zZXNfMjAyMi5jc3YiKQ0KYGBgDQoNCmBgYHtyfQ0KYmxhaXJfZXhwZW5zZXNfMjAyMl9jbGVhbmVkIDwtYmxhaXJfZXhwZW5zZXNfMjAyMiAlPiUgDQogIGNsZWFuX25hbWVzIA0KYGBgDQoNCmBgYHtyfQ0KYmxhaXJfZXhwZW5zZXNfMjAyMl9jbGVhbmVkICU+JSANCm11dGF0ZShjb250cmlidXRpb25fZGF0ZSA9IG1keShleHBlbmRpdHVyZV9kYXRlKSkgDQoNCmJsYWlyX2V4cGVuc2VzXzIwMjJfY2xlYW5lZA0KYGBgDQoNCiMjI0JsYWlyIDIwMTggZXhwZW5zZXMNCg0KDQpgYGB7cn0NCmJsYWlyX2V4cGVuc2VzXzIwMTggPC1yZWFkLmNzdigiZGF0YTIvYmxhaXJfZXhwZW5zZXNfMjAxOC5jc3YiKQ0KYGBgDQoNCmBgYHtyfQ0KYmxhaXJfZXhwZW5zZXNfMjAxOF9jbGVhbmVkIDwtYmxhaXJfZXhwZW5zZXNfMjAxOCAlPiUgDQogIGNsZWFuX25hbWVzKCkNCmBgYA0KDQpgYGB7cn0NCmJsYWlyX2V4cGVuc2VzXzIwMThfY2xlYW5lZCAlPiUgDQogIG11dGF0ZShjb250cmlidXRpb25fZGF0ZSA9IG1keShleHBlbmRpdHVyZV9kYXRlKSkgDQpibGFpcl9leHBlbnNlc18yMDE4X2NsZWFuZWQgDQpgYGANCg0KIyNFbHJpY2ggMjAxOCBjb250cmliczoNCg0KYGBge3J9DQplbHJpY2hfY29udHJpYnNfMjAxOCA8LXJlYWQuY3N2KCJkYXRhMi9lbHJpY2hfY29udHJpYnNfMjAxOC5jc3YiKQ0KYGBgDQoNCmBgYHtyfQ0KZWxyaWNoX2NvbnRyaWJzXzIwMThfY2xlYW5lZCA8LWVscmljaF9jb250cmlic18yMDE4ICU+JSANCiAgY2xlYW5fbmFtZXMoKQ0KYGBgDQoNCmBgYHtyfQ0KZWxyaWNoX2NvbnRyaWJzXzIwMThfY2xlYW5lZCAlPiUgDQogIG11dGF0ZShjb250cmlidXRpb25fZGF0ZSA9IG1keShjb250cmlidXRpb25fZGF0ZSkpIA0KDQplbHJpY2hfY29udHJpYnNfMjAxOF9jbGVhbmVkDQpgYGANCg0KIyMjRWxyaWNoIENvbnRyaWJzIDIwMjINCg0KYGBge3J9DQplbHJpY2hfY29udHJpYnNfMjAyMiA8LXJlYWQuY3N2KCJkYXRhMi9lbHJpY2hfY29udHJpYnNfMjAyMi5jc3YiKQ0KYGBgDQoNCmBgYHtyfQ0KZWxyaWNoX2NvbnRyaWJzXzIwMjJfY2xlYW5lZCA8LWVscmljaF9jb250cmlic18yMDIyICU+JQ0KICBjbGVhbl9uYW1lcygpDQpgYGANCg0KYGBge3J9DQplbHJpY2hfY29udHJpYnNfMjAyMl9jbGVhbmVkICU+JSANCiAgbXV0YXRlKGNvbnRyaWJ1dGlvbl9kYXRlID0gbWR5KGNvbnRyaWJ1dGlvbl9kYXRlKSkgDQoNCmVscmljaF9jb250cmlic18yMDIyX2NsZWFuZWQNCmBgYA0KDQojIyNFbHJpY2ggMjAxOA0KDQpgYGB7cn0NCmVscmljaF9leHBlbnNlc18yMDE4IDwtcmVhZC5jc3YoImRhdGEyL2VscmljaF9leHBlbnNlc18yMDE4LmNzdiIpDQpgYGANCg0KYGBge3J9DQplbHJpY2hfZXhwZW5zZXNfMjAxOF9jbGVhbmVkIDwtZWxyaWNoX2V4cGVuc2VzXzIwMTggJT4lIA0KICBjbGVhbl9uYW1lcygpDQpgYGANCg0KYGBge3J9DQplbHJpY2hfZXhwZW5zZXNfMjAxOF9jbGVhbmVkICU+JSANCiAgICBtdXRhdGUoY29udHJpYnV0aW9uX2RhdGUgPSBtZHkoZXhwZW5kaXR1cmVfZGF0ZSkpIA0KZWxyaWNoX2V4cGVuc2VzXzIwMThfY2xlYW5lZA0KYGBgDQojIyNFbHJpY2ggRXhwZW5zZXMgMjAyMg0KDQpgYGB7cn0NCmVscmljaF9leHBlbnNlc18yMDIyIDwtcmVhZC5jc3YoImRhdGEyL2VscmljaF9leHBlbnNlc18yMDIyLmNzdiIpDQpgYGANCg0KYGBge3J9DQplbHJpY2hfZXhwZW5zZXNfMjAyMl9jbGVhbmVkIDwtZWxyaWNoX2V4cGVuc2VzXzIwMjIgJT4lIA0KICBjbGVhbl9uYW1lcygpDQpgYGANCg0KYGBge3J9DQplbHJpY2hfZXhwZW5zZXNfMjAyMl9jbGVhbmVkICU+JSANCiAgbXV0YXRlKGNvbnRyaWJ1dGlvbl9kYXRlID0gbWR5KGV4cGVuZGl0dXJlX2RhdGUpKSANCmVscmljaF9leHBlbnNlc18yMDIyX2NsZWFuZWQNCmBgYA0KDQoNCiMjQ291bnR5IHByaW1hcnkgZWxlY3Rpb24gcmVzdWx0czoNCg0KDQoNCmBgYHtyfQ0KZGVtX3ByZWNpbmN0c18xOCA8LSByZWFkLmNzdigiZGF0YTIvZGVtX3ByZWNpbmN0c18yMDE4LmNzdiIpDQpgYGANCg0KYGBge3J9DQpkZW1fcHJlY2luY3RzXzIyIDwtIHJlYWQuY3N2KCJkYXRhMi9kZW1fcHJlY2luY3RzXzIwMjIuY3N2IikNCmBgYA0KDQoNCg0KDQoNCmBgYHtyfQ0KZGVtX2NvdW50eV8yMiA8LSByZWFkLmNzdigiZGF0YTIvZGVtX2NvdW50eV8yMDIyLmNzdiIpDQpgYGANCg0KYGBge3J9DQpkZW1fY291bnR5XzE4IDwtIHJlYWQuY3N2KCJkYXRhMi9kZW1fY291bnR5XzIwMTguY3N2IikNCmBgYA0KDQoNCg0KDQojIyNRdWVzdGlvbiAxIDEuIEhvdyBtdWNoIG1vbmV5IGRpZCBEYXZpZCBCbGFpciBhbmQgTWFyYyBFbHJpY2ggZnVuZCB0aGVtc2VsdmVzIGluIDIwMjIgdnMuIDIwMTg/IEJsYWlyIGlzIGEgYnVzaW5lc3NtYW4gYW5kIG1pbGxpb25haXJlLCBzbyBpdCBtYWtlcyBzZW5zZSB0aGF0IGhl4oCZcyBmdW5kaW5nIGhpcyBvd24gY2FtcGFpZ24uIEJ1dCBob3cgbXVjaCBleGFjdGx5IGlzIGhlIHB1dHRpbmcgaW50byBpdCwgYW5kIGhvdyBkb2VzIGl0IGNvbXBhcmUgdG8gdGhlIHBhc3QgZWxlY3Rpb24gYW5kIHRvIGhvdyBtdWNoIEVscmljaOKAmXMgY2FtcGFpZ24gaXMgcmFpc2luZz8NCg0KIyMjMjAyMjoNCg0KYGBge3J9DQpibGFpcl9jb250cmlic18yMDIyX2NsZWFuZWQgJT4lDQpmaWx0ZXIoY29udHJpYnV0b3JfbmFtZSA9PSAiQkxBSVIgIERBVklEICBUSE9NQVMiKSAlPiUNCmdyb3VwX2J5KGNvbnRyaWJ1dG9yX25hbWUpICU+JQ0Kc3VtbWFyaXplKHRvdGFsX2JsYWlyID0gc3VtKGNvbnRyaWJ1dGlvbl9hbW91bnQpKQ0KYGBgDQoNCmBgYHtyfQ0KZWxyaWNoX2NvbnRyaWJzXzIwMjJfY2xlYW5lZCAlPiUNCmdyb3VwX2J5KGNvbnRyaWJ1dG9yX25hbWUpICU+JQ0Kc3VtbWFyaXplKHRvdGFsX2VscmljaCA9IHN1bShjb250cmlidXRpb25fYW1vdW50KSkgJT4lDQphcnJhbmdlKGRlc2ModG90YWxfZWxyaWNoKSkNCmBgYA0KIyMjMjAxODoNCg0KYGBge3J9DQpibGFpcl9jb250cmlic18yMDE4X2NsZWFuZWQgJT4lDQpmaWx0ZXIoY29udHJpYnV0b3JfbmFtZSA9PSAiQkxBSVIgIERBVklEICBUSE9NQVMiKSAlPiUNCmdyb3VwX2J5KGNvbnRyaWJ1dG9yX25hbWUpICU+JQ0Kc3VtbWFyaXplKHRvdGFsX2JsYWlyID0gc3VtKGNvbnRyaWJ1dGlvbl9hbW91bnQpKQ0KYGBgDQpgYGB7cn0NCmVscmljaF9jb250cmlic18yMDE4X2NsZWFuZWQgJT4lDQpncm91cF9ieShjb250cmlidXRvcl9uYW1lKSAlPiUNCnN1bW1hcml6ZSh0b3RhbF9lbHJpY2ggPSBzdW0oY29udHJpYnV0aW9uX2Ftb3VudCkpICU+JQ0KYXJyYW5nZShkZXNjKHRvdGFsX2VscmljaCkpDQpgYGANCiANCiMjI1F1ZXN0aW9uIDI6IFdobyB3ZXJlIHRoZSB0b3AgNSBjb250cmlidXRvcnMgdG8gQmxhaXIgYW5kIEVscmljaCBpbiAyMDIyPyBIb3cgYWJvdXQgaW4gMjAxOD8gV2hhdCBhcmUgdGhlaXIgY29ubmVjdGlvbnMgdG8gdGhlIGNhbmRpZGF0ZXM/DQoNCg0KIyMjMjAyMg0KYGBge3J9DQp0b3BfYmxhaXJfY29udHJpYnNfMjIgPC0gYmxhaXJfY29udHJpYnNfMjAxOF9jbGVhbmVkICU+JQ0KICBtdXRhdGUoY29udHJpYnV0b3JfbmFtZSA9IGNhc2Vfd2hlbigNCiAgICBjb250cmlidXRvcl9uYW1lID09ICJCTEFJUiAgREFWSUQgIFRIT01BUyIgfiAiQmxhaXIgIERhdmlkICBUaG9tYXMiLA0KICAgIFRSVUUgfiBjb250cmlidXRvcl9uYW1lDQogICkpICU+JQ0KICBncm91cF9ieShjb250cmlidXRvcl9uYW1lKSAlPiUNCiAgc3VtbWFyaXplKHRvdGFsID0gc3VtKGNvbnRyaWJ1dGlvbl9hbW91bnQpKSAlPiUNCiAgYXJyYW5nZShkZXNjKHRvdGFsKSkgJT4lDQogIGhlYWQoNSkNCnRvcF9ibGFpcl9jb250cmlic18yMg0KYGBgDQoNCmBgYHtyfQ0KdG9wX2VscmljaF9jb250cmlic18yMiA8LSBlbHJpY2hfY29udHJpYnNfMjAyMl9jbGVhbmVkICU+JQ0KICBncm91cF9ieShjb250cmlidXRvcl9uYW1lKSAlPiUNCiAgc3VtbWFyaXplKHRvdGFsID0gc3VtKGNvbnRyaWJ1dGlvbl9hbW91bnQpKSAlPiUNCiAgYXJyYW5nZShkZXNjKHRvdGFsKSkgJT4lDQogIGhlYWQoNikNCnRvcF9lbHJpY2hfY29udHJpYnNfMjINCmBgYA0KDQojIyMyMDE4DQoNCmBgYHtyfQ0KdG9wX2JsYWlyX2NvbnRyaWJzXzE4IDwtIGJsYWlyX2NvbnRyaWJzXzIwMThfY2xlYW5lZCAlPiUNCiAgbXV0YXRlKGNvbnRyaWJ1dG9yX25hbWUgPSBjYXNlX3doZW4oDQogICAgY29udHJpYnV0b3JfbmFtZSA9PSAiQkxBSVIgIERBVklEICBUSE9NQVMiIH4gIkJsYWlyICBEYXZpZCAgVGhvbWFzIiwNCiAgICBUUlVFIH4gY29udHJpYnV0b3JfbmFtZQ0KICApKSAlPiUNCiAgZ3JvdXBfYnkoY29udHJpYnV0b3JfbmFtZSkgJT4lDQogIHN1bW1hcml6ZSh0b3RhbCA9IHN1bShjb250cmlidXRpb25fYW1vdW50KSkgJT4lDQogIGFycmFuZ2UoZGVzYyh0b3RhbCkpICU+JQ0KICBoZWFkKDUpDQp0b3BfYmxhaXJfY29udHJpYnNfMTgNCmBgYA0KDQpgYGB7cn0NCnRvcF9lbHJpY2hfY29udHJpYnNfMTggPC0gZWxyaWNoX2NvbnRyaWJzXzIwMThfY2xlYW5lZCAlPiUNCiAgZ3JvdXBfYnkoY29udHJpYnV0b3JfbmFtZSkgJT4lDQogIHN1bW1hcml6ZSh0b3RhbCA9IHN1bShjb250cmlidXRpb25fYW1vdW50KSkgJT4lDQogIGFycmFuZ2UoZGVzYyh0b3RhbCkpICU+JQ0KICBoZWFkKDYpDQp0b3BfZWxyaWNoX2NvbnRyaWJzXzE4DQpgYGANCg0KIyMjUXVlc3Rpb24gMzogRGF2aWQgQmxhaXIgZ290IG1vcmUgZWFybHkvZWxlY3Rpb24gZGF5IHZvdGVzIGluIDIwMjIuIEVscmljaCBnb3QgbW9yZSBNYWlsLWluIHZvdGVzIGluIDIwMjIuIEhvdyBkaWQgdGhhdCBjb21wYXJlIHRvIDIwMTg/IFBlb3BsZSB3YW50IHRvIGtub3cgaG93IE1hcmMgRWxyaWNoIHdvbiBib3RoIHRpbWVzLCBmaXJzdCBieSA3MiB2b3RlcnMgaW4gMjAxOCBhbmQgdGhlbiAzMiBpbiAyMDIyLiBXaGVyZSBkaWQgTWFyYyBkbyB3ZWxsIGluIHRoZSB0aHJlZSBjYXRlZ29yaWVzOiBFYXJseSB2b3RpbmcsIGVsZWN0aW9uIGRheSwgYW5kIG1haWwtaW4gdm90ZXMuIERpZCB0aGlzIHN3YXkgdGhlIHJlc3VsdCBhdCBhbGw/DQoNCmBgYHtyfQ0KZGVtX2NvdW50eV8xOF9jbGVhbmVkIDwtZGVtX2NvdW50eV8xOCAlPiUgDQogIGNsZWFuX25hbWVzKCkNCmBgYA0KDQoNCmBgYHtyfQ0KZGVtX2NvdW50eV8yMl9jbGVhbmVkIDwtZGVtX2NvdW50eV8yMiAlPiUgDQogIGNsZWFuX25hbWVzKCkNCmBgYA0KDQoNCg0KYGBge3J9DQoNCmJsYWlyIDwtIGRlbV9jb3VudHlfMThfY2xlYW5lZCAlPiUNCmZpbHRlcihjYW5kaWRhdGVfbmFtZSA9PSAiRGF2aWQgQmxhaXIiKQ0KZWxyaWNoIDwtICBkZW1fY291bnR5XzE4X2NsZWFuZWQgJT4lDQogIGZpbHRlcihjYW5kaWRhdGVfbmFtZSA9PSAiTWFyYyBFbHJpY2giKQ0KYmxhaXJfZWxyaWNoIDwtICBiaW5kX3Jvd3MoYmxhaXIsIGVscmljaCkNCmJsYWlyX2VscmljaA0KYGBgDQoNCg0KDQoNCg0KIyMjUXVlc3Rpb24gNDogV2hpY2ggcGFydHMgb2YgdGhlIGNvdW50eSB2b3RlZCBmb3IgRWxyaWNoIGFuZCB3aGljaCB2b3RlZCBmb3IgQmxhaXIgYmFzZWQgb24gcHJlY2luY3QtbGV2ZWwgdm90aW5nPyBBcmUgdGhlcmUgZGlmZmVyZW5jZXMgaW4gZGVtb2dyYXBoaWNzIG9mIHRob3NlIGFyZWFzPyBXaGF0IGFib3V0IGluY29tZT8gDQoNClxcDQoNCmBgYHtyfQ0KbGlicmFyeShzZikNCmBgYA0KDQpgYGB7cn0NCm1vY29fcHJlY18yMDIyIDwtIHN0X3JlYWQoImRhdGEyL01vbnRNRF8yMDIyL01vbnRNRF8yMDIyLnNocCIpICU+JSANCiAgc3Rfem0oZHJvcD1UUlVFKQ0KZ2xpbXBzZShtb2NvX3ByZWNfMjAyMikNCmBgYA0KDQoNCg0KDQpgYGB7cn0NCm1vY29fYm91bmRhcmllcyA8LSBzdF9yZWFkKCJkYXRhMi9tb2NvX2JvdW5kYXJ5LmdkYiIpDQoNCmdsaW1wc2UobW9jb19ib3VuZGFyaWVzKQ0KYGBgDQoNCg0KYGBge3J9DQptb2NvX2JvdW5kYXJpZXMgJT4lDQogIGdncGxvdCgpICsNCiAgZ2VvbV9zZigpICsNCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANCmBgYHtyfQ0KbW9jb19wcmVjXzIwMjINCmhlYWQobW9jb19wcmVjXzIwMjIpDQpgYGANCmBgYHtyfQ0Kd3JpdGVfY3N2KG1vY29fcHJlY18yMDIyLCAiZGF0YTIvbW9jb19wcmVjXzIwMjIuY3N2IikNCmBgYA0KDQpgYGB7cn0NCm1vY29fcHJlY18yMDIyICU+JQ0KICBnZ3Bsb3QoKSArDQogIGdlb21fc2YoKSArDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQpgYGB7cn0NCm1vY29fMjJfcHJlX3Jlc3VsdHM8LXJlYWQuY3N2KCJkYXRhMi9Nb2NvXzIyX3ByZV9yZXN1bHRzLmNzdiIpDQpoZWFkKG1vY29fMjJfcHJlX3Jlc3VsdHMpDQpgYGANCg0KYGBge3J9DQptb2NvXzIyX3ByZV9yZXN1bHRzX2NsZWFuZWQgPC1tb2NvXzIyX3ByZV9yZXN1bHRzICU+JSANCiAgY2xlYW5fbmFtZXMoKQ0KbW9jb18yMl9wcmVfcmVzdWx0c19jbGVhbmVkDQpgYGANCg0KDQoNCg0KYGBge3J9DQptb2NvXzIyX3ByZV9yZXN1bHRzX2ZpbHRlcmVkPC1tb2NvXzIyX3ByZV9yZXN1bHRzX2NsZWFuZWQgJT4lDQpmaWx0ZXIoY2FuZGlkYXRlX25hbWUgPT0gIkRhdmlkIFQuIEJsYWlyIiB8IGNhbmRpZGF0ZV9uYW1lID09ICJNYXJjIEVscmljaCIpDQptb2NvXzIyX3ByZV9yZXN1bHRzX2ZpbHRlcmVkDQpgYGANCmBgYHtyfQ0KYmxhaXJfcmVzdWx0c18yMDIyX2ZpbHRlcjwtbW9jb18yMl9wcmVfcmVzdWx0c19maWx0ZXJlZCAlPiUgDQogIGZpbHRlcihjYW5kaWRhdGVfbmFtZSA9PSAiRGF2aWQgVC4gQmxhaXIiKQ0KYmxhaXJfcmVzdWx0c18yMDIyX2ZpbHRlcg0KYGBgDQoNCg0KDQoNCmBgYHtyfQ0KYmxhaXJfcmVzdWx0c18yMDIyX2ZpbHRlcl90b3RhbCA8LWJsYWlyX3Jlc3VsdHNfMjAyMl9maWx0ZXIlPiUgDQogIG11dGF0ZSh0b3RhbF92b3Rlc19ibGFpciA9IGVhcmx5X3ZvdGVzICsgZWxlY3Rpb25fbmlnaHRfdm90ZXMgKyBtYWlsX2luX2JhbGxvdF8xX3ZvdGVzICsgcHJvdmlzaW9uYWxfdm90ZXMgKyBtYWlsX2luX2JhbGxvdF8yX3ZvdGVzKQ0KYmxhaXJfcmVzdWx0c18yMDIyX2ZpbHRlcl90b3RhbA0KYGBgDQpgYGB7cn0NCmJsYWlyX3Jlc3VsdHNfam9pbmVkXzIwMjI8LSBpbm5lcl9qb2luKG1vY29fcHJlY18yMDIyLCBibGFpcl9yZXN1bHRzXzIwMjJfZmlsdGVyX3RvdGFsLCBieT1jKCJWT1RFU1BSRSI9ImVsZWN0aW9uX2Rpc3RyaWN0X3ByZWNpbmN0IikpDQpgYGANCg0KDQoNCg0KIyMjQmxhaXIgTWFwIyMjIw0KYGBge3J9DQpnZ3Bsb3QoKSArDQogIGdlb21fc2YoZGF0YT1ibGFpcl9yZXN1bHRzX2pvaW5lZF8yMDIyLCBhZXMoZmlsbD10b3RhbF92b3Rlc19ibGFpcikpICsNCiAgc2NhbGVfZmlsbF92aXJpZGlzX2Iob3B0aW9uPSJtYWdtYSIpKw0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KIyMjI0VsaXJpY2ggbWFwIyMjIw0KYGBge3J9DQptb2NvXzIyX3ByZV9yZXN1bHRzX2ZpbHRlcmVkX2VscmljaCA8LW1vY29fMjJfcHJlX3Jlc3VsdHNfY2xlYW5lZCAlPiUNCmZpbHRlcihjYW5kaWRhdGVfbmFtZSA9PSAiTWFyYyBFbHJpY2giKQ0KbW9jb18yMl9wcmVfcmVzdWx0c19maWx0ZXJlZF9lbHJpY2gNCmBgYA0KYGBge3J9DQplbHJpY2hfMjJfZmlsdGVyZWRfdG90YWwgPC1tb2NvXzIyX3ByZV9yZXN1bHRzX2ZpbHRlcmVkX2VscmljaCU+JSANCiAgbXV0YXRlKHRvdGFsX3ZvdGVzX2VscmljaCA9IGVhcmx5X3ZvdGVzICsgZWxlY3Rpb25fbmlnaHRfdm90ZXMgKyBtYWlsX2luX2JhbGxvdF8xX3ZvdGVzICsgcHJvdmlzaW9uYWxfdm90ZXMgKyBtYWlsX2luX2JhbGxvdF8yX3ZvdGVzKQ0KZWxyaWNoXzIyX2ZpbHRlcmVkX3RvdGFsDQpgYGANCmBgYHtyfQ0KZWxyaWNoX3Jlc3VsdHNfam9pbmVkXzIwMjJfbWFwPC0gaW5uZXJfam9pbihtb2NvX3ByZWNfMjAyMiwgZWxyaWNoXzIyX2ZpbHRlcmVkX3RvdGFsLCBieT1jKCJWT1RFU1BSRSI9ImVsZWN0aW9uX2Rpc3RyaWN0X3ByZWNpbmN0IikpDQpgYGANCg0KYGBge3J9DQpnZ3Bsb3QoKSArDQogIGdlb21fc2YoZGF0YT1lbHJpY2hfcmVzdWx0c19qb2luZWRfMjAyMl9tYXAsIGFlcyhmaWxsPXRvdGFsX3ZvdGVzX2VscmljaCkpICsNCiAgc2NhbGVfZmlsbF92aXJpZGlzX2Iob3B0aW9uPSJtYWdtYSIpKw0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KIyMjcGVyY2VudGFnZV9jaGFuZ2UqKioNCmBgYHtyfQ0KYmxhaXJfcmVzdWx0c18yMDIyX2ZpbHRlcl90b3RhbA0KYGBgDQoNCmBgYHtyfQ0KZWxyaWNoXzIyX2ZpbHRlcmVkX3RvdGFsDQpgYGANCg0KDQpgYGB7cn0NCmJvdGhfam9pbmVkXzIwMjI8LSBsZWZ0X2pvaW4oYmxhaXJfcmVzdWx0c18yMDIyX2ZpbHRlcl90b3RhbCwgZWxyaWNoXzIyX2ZpbHRlcmVkX3RvdGFsLCBieT1jKCJjb3VudHkiPSJjb3VudHkiKSkNCmBgYA0KDQpgYGB7cn0NCmJvdGhfam9pbmVkXzIwMjINCmBgYA0KYGBge3J9DQpib3RoX2pvaW5lZF9tdXRhdGVkPC1ib3RoX2pvaW5lZF8yMDIyICU+JSANCiAgbXV0YXRlKGRpZmZlcmVuY2UgPSB0b3RhbF92b3Rlc19lbHJpY2gtdG90YWxfdm90ZXNfYmxhaXIpDQpib3RoX2pvaW5lZF9tdXRhdGVkDQoNCmBgYA0KYGBge3J9DQpib3RoX2pvaW5lZF9tYXA8LSBpbm5lcl9qb2luKG1vY29fcHJlY18yMDIyLCBib3RoX2pvaW5lZF9tdXRhdGVkLCBieT1jKCJWT1RFU1BSRSI9ImVsZWN0aW9uX2Rpc3RyaWN0X3ByZWNpbmN0LngiKSkNCmBgYA0KDQpgYGB7cn0NCmdncGxvdCgpICsNCiAgZ2VvbV9zZihkYXRhPWJvdGhfam9pbmVkX21hcCwgYWVzKGZpbGw9ZGlmZmVyZW5jZSkpICsNCiAgc2NhbGVfZmlsbF92aXJpZGlzX2Iob3B0aW9uPSJtYWdtYSIpKw0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KDQoNCg0KDQoNCg0KDQoNCmBgYHtyfQ0KbGlicmFyeShnZ3Bsb3QyKQ0KYGBgDQoNCmBgYHtyfQ0KZ2dwbG90KHJlc3VsdHNfam9pbmVkXzIwMjIpKw0KICBnZW9tX21hcChhZXMobWFwX2lkID0gcmVnaW9uKSkrDQogIGV4cGFuZF9saW1pdHMoKQ0KYGBgDQoNCg0KIyMjUXVlc3Rpb24gNTogV2hlcmUgZGlkIERhdmlkIEJsYWlyIGFuZCBNYXJjIEVscmljaCBzcGVuZCB0aGVpciBtb25leSBvbiBjYW1wYWlnbiBmaW5hbmNlIHJlc291cmNlcz8gSWU6IE1ldGEgYWR2ZXJ0aXNlbWVudHMsIHlhcmQgc2lnbnMsIFRWLCBjb25zdWx0aW5nPyBUaGlzIHdvdWxkIGJlIGludGVyZXN0aW5nIHRvIGtub3cgc2luY2UgQmxhaXIgbWFkZSBhIHZlcnkgYmlnIGNvbmNlcnRlZCBlZmZvcnQgdG8gYnVpbGQgaGlzIHByb2ZpbGUgZHVyaW5nIHRoZSBjYW1wYWlnbiB3aGlsZSBFbHJpY2ggcmVsaWVkIG9uIGluY3VtYmVuY3kgYW5kIG1haW5seSBUViBhZHMgdG8gaGVscCBoaW0uIA0KDQoNCmBgYHtyfQ0KYmxhaXJfZXhwZW5zZXNfMjAyMl9jbGVhbmVkICU+JQ0KZ3JvdXBfYnkoZXhwZW5zZV9jYXRlZ29yeSkgJT4lDQpzdW1tYXJpemUodG90YWxfY2F0ZWdvcnkgPSBzdW0oYW1vdW50KSkgJT4lDQphcnJhbmdlKGRlc2ModG90YWxfY2F0ZWdvcnkpKQ0KI3NwZW50IG5lYXJseSAkMy4xIG1pbCBpbiAyMDIyIC4uLiB0b3AgMyBhcmUgTWVkaWEsIFNhbGFydGllcyBhbmQgRGlyZWN0IE1haWwgYnkgTWFpbCBIb3VzZSAoUikNCmBgYA0KI2RpdmUgaW50byBtZWRpYQ0KYGBge3J9DQpibGFpcl9leHBlbnNlc18yMDIyX2NsZWFuZWQgJT4lDQpmaWx0ZXIoZXhwZW5zZV9jYXRlZ29yeSA9PSAiTWVkaWEiKSAlPiUNCmdyb3VwX2J5KGV4cGVuc2VfcHVycG9zZSkgJT4lDQpzdW1tYXJpemUodG90YWxfY2F0ZWdvcnkgPSBzdW0oYW1vdW50KSkgJT4lDQphcnJhbmdlKGRlc2ModG90YWxfY2F0ZWdvcnkpKQ0KYGBgDQojIFNwZW50IDE3NzMuMDAJIG9uIG9ubGluZSBhZHZlcnRpc2luZw0KDQpgYGB7cn0NCmVscmljaF9leHBlbnNlc18yMDIyX2NsZWFuZWQgJT4lDQpncm91cF9ieShleHBlbnNlX2NhdGVnb3J5KSAlPiUNCnN1bW1hcml6ZSh0b3RhbF9jYXRlZ29yeSA9IHN1bShhbW91bnQpKSAlPiUNCmFycmFuZ2UoZGVzYyh0b3RhbF9jYXRlZ29yeSkpDQpgYGANCkVscmljaCBzcGVudCAkNTI4MzkzLjI5IG9uIG1lZGlhIHdoaWNoIGlzIHNpZ25pZmljYW50bHkgbGVzcyB0aGFuIEJsYWlyDQoNCmBgYHtyfQ0KZWxyaWNoX2V4cGVuc2VzXzIwMjJfY2xlYW5lZCAlPiUNCmZpbHRlcihleHBlbnNlX2NhdGVnb3J5ID09ICJNZWRpYSIpICU+JQ0KZ3JvdXBfYnkoZXhwZW5zZV9wdXJwb3NlKSAlPiUNCnN1bW1hcml6ZSh0b3RhbF9jYXRlZ29yeSA9IHN1bShhbW91bnQpKSAlPiUNCmFycmFuZ2UoZGVzYyh0b3RhbF9jYXRlZ29yeSkpDQpgYGANCg0KI0VscmljaCBzcGVudCAzMksgb24gY29uc3VsdGluZyBmZWVzLg0KDQpUaGlzIGlzIHdoYXQgSSB3cm90ZSBmb3IgTm8uIDUgIlRoZXJlIGFyZSBzaWduaWZhbnQgZGlmZmVyZW5jZXMgaW4gc3BlbmRpbmcgYmV0d2VlbiBFbHJpY2ggYW5kIEJsYWlyIGhlcmUgYW5kIGl0IHNob3dzIGhvdyB0aGUgY2FwaXRhbCBvbiBoYW5kIGNhbiByZWFsbHkgaW5mbHVlbmNlIHRoZSBtZWFucyBhIGNhbmRpZGF0ZSBoYXMgdG8gd2luIG9yIGxvc2UgYSByYWNlLiBFbHJpY2ggaW4gMjAyMiB3ZW50IGFsbC1pbiBvbiBUViBzcGVuZGluZy4gQmxhaXIgc3BlbnQgYSBsb3QgbW9yZSBpbiAyMDE4IGFzIHdlbGwuIg==